package guggaTests.tasks
{
	import flexunit.framework.TestCase;
	import gugga.tasks.events.TaskEvent;
	import gugga.tasks.SingleExecutionTask;
	import gugga.tasks.ITask;
	import gugga.tasks.FictiveTask;
	import gugga.tasks.WaitingTask;
	import gugga.utils.DoLaterUtil;

	public class SingleExecutionTaskTest extends TestCase
	{
		private var delayInterval:Number = 1000;
		
		private var mIsTaskExecuted : Boolean = false;
		private var mTaskExecutionsCount : Number = 0;
	
		public function SingleExecutionTaskTest(methodName:String=null)
		{
			super(methodName);
		}
		
		public function testConstructor () : void
		{
			var actualTask : ITask = new FictiveTask();
			var task : ITask = new SingleExecutionTask(actualTask);
			
			assertTrue(
				"the constructor should return an instance of the SingleExecutionTask class",
				task is SingleExecutionTask
				);
		}
		
		public function testStartAndCompletion () : void
		{
			var actualTask : ITask = new FictiveTask();
			var task : SingleExecutionTask = new SingleExecutionTask(actualTask);
			
			task.addEventListener(TaskEvent.START, onSingleExecutionTaskStarted);
			task.addEventListener(TaskEvent.COMPLETED, addAsync(assertSingleExecutionTaskCompleted, 100));
			task.start();

			assertTrue("Task should be executed", mIsTaskExecuted);
		}
		
		public function testSingleExecution () : void
		{			
			var actualTask : ITask = new FictiveTask();
			var task : ITask = new SingleExecutionTask(actualTask);
			
			task.addEventListener(TaskEvent.START, onSingleExecutionTaskStarted);
			task.addEventListener(TaskEvent.COMPLETED, addAsync(assertSingleExecutionTaskCompleted, 100))
			
			task.start()
			
			assertTrue("Task should be executed", mIsTaskExecuted);
			
			task.start();
		}
		
		public function testIsRunningWithWaitingTask() : void
		{
			var actualTask : ITask = new WaitingTask(0.01);
			var singleExecutionTask : ITask = new SingleExecutionTask(actualTask);
			
			singleExecutionTask.addEventListener(TaskEvent.START, onSingleExecutionTaskStarted);
			singleExecutionTask.addEventListener(TaskEvent.COMPLETED, addAsync(assertSingleExecutionTaskCompleted, 1000));
			
			assertFalse("SingleExecutionTask should not be running", singleExecutionTask.isRunning());
			
			singleExecutionTask.start();
			
			assertTrue("SingleExecutionTask should be running", singleExecutionTask.isRunning());
		}
		
		public function testInterrupt() : void
		{
			var actualTask : ITask = new WaitingTask(0.01);
			var singleExecutionTask : ITask = new SingleExecutionTask(actualTask);
			
			singleExecutionTask.addEventListener(TaskEvent.INTERRUPTED, addAsync(assertSingleExecutionTaskInterrupt, 300));
			
			singleExecutionTask.start();
			
			DoLaterUtil.doLater(singleExecutionTask.interrupt, null, 1, singleExecutionTask);
		}
		
		private function onSingleExecutionTaskStarted(aEvent : TaskEvent) : void
		{
			mIsTaskExecuted = true;
			mTaskExecutionsCount++;
		}
		
		private function assertSingleExecutionTaskCompleted(aEvent : TaskEvent) : void
		{
			var task : ITask = ITask(aEvent.target);
			
			assertFalse("Task should not be running", task.isRunning());
			
			assertEquals("Single execution task should be started once", 1, mTaskExecutionsCount);	
		}
		
		private function assertSingleExecutionTaskStarted(aEvent : TaskEvent) : void
		{
			var task : ITask = ITask(aEvent.target);
			
			assertTrue("SingleExecutionTask should be running", task.isRunning());
		}
		
		private function assertSingleExecutionTaskInterrupt(aEvent : TaskEvent) : void
		{
			var task : ITask = ITask(aEvent.target);
			
			assertFalse("Task should not be running", task.isRunning());			
		}
		
		public override function setUp() : void
		{
			mIsTaskExecuted = false;
			mTaskExecutionsCount = 0;
		}
	}
}